<template>
  <form class="validate-from-container">
    <slot name="default"></slot>
    <div class="submit-area" @click.prevent="submitForm">
      <slot name="submit">
        <button type="submit" class="btn btn-primary">提交</button>
      </slot>
    </div>
  </form>
</template>

<script lang="ts">
import { defineComponent, onUnmounted } from 'vue'
import mitt from 'mitt'
type ValidateFunc = () => boolean
type ValiClearFunc = () => void
type Events = {
  'form-item-created': ValidateFunc,
  'clear-input-value': ValiClearFunc
}

export const emitter = mitt<Events>()
export default defineComponent({
  name: 'ValidateForm',
  emits: ['form-submit'],
  setup (props, context) {
    // 清除validateInput值
    const clearInputs = () => {
      clearFuncArr.map(item => item())
    } // 异步清除方法，点击提交时，循环调用清除方法
    const clearFuncArr: ValiClearFunc[] = []
    const clearCallback = (func: ValiClearFunc) => { // 回调，往数组中push清除方法
      clearFuncArr.push(func)
    }
    emitter.on('clear-input-value', clearCallback) // 监听清除方法

    // 处理表单验证结果
    let funcArr: ValidateFunc[] = []
    // 处理数组中的表单验证方法
    const submitForm = () => { // 在提交按钮点击事件中，把函数数组中的函数依次执行一遍，形成新的由boolean 组成的数组，再使用every判断是否全部通过验证
      const result = funcArr.map(item => item()).every(result => result)
      context.emit('form-submit', result)// 把结果发射到父组件
      clearInputs()
    }
    // 通过监听回调，把方法都添加到数组中
    const callback = (func: ValidateFunc) => { // 回调函数 向函数数组中push 发射过来的函数
      if (func) {
        funcArr.push(func)
      }
    }
    // 监听Input组件发射过来的表单验证方法
    emitter.on('form-item-created', callback) // 开始监听事件，监听事件调用回调函数。回调函数接收发射过来的值
    onUnmounted(() => { // 卸载的时候 停止事件,清空数组中的函数
      emitter.off('form-item-created', callback)
      funcArr = []
    })

    return { submitForm }
  }
})
</script>
